package com.mickey.access;

import com.alibaba.fastjson.JSON;
import com.mickey.domain.MiaoshaUser;
import com.mickey.redis.AccessKey;
import com.mickey.redis.RedisService;
import com.mickey.result.CodeMsg;
import com.mickey.result.Result;
import com.mickey.service.Imp.MiaoshaUserUserServiceImp;
import com.mickey.service.MiaoshaUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;

/**
 * @Desc:注解限流拦截器
 * @Author:czx
 * @CreateDate:2019/1/11 0011$ 20:08$
 */
@Service
public class AccessInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private MiaoshaUserService miaoshaUserService;

    @Autowired
    private RedisService redisService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod){
            MiaoshaUser user = getUser(request,response);
            UserContext.setUser(user);//用户存入线程变量

            HandlerMethod hm = (HandlerMethod) handler;
            AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);//获取注解
            if (accessLimit==null){
                return true;
            }
            int seconds = accessLimit.seconds();//几秒内
            int maxCount = accessLimit.maxCount();//最多可访问次数
            boolean needLogin = accessLimit.needLogin();//是否需要登录

            String key = request.getRequestURI();
            if (needLogin){
                if(user == null){
                    render(response, CodeMsg.SESSION_ERROR);
                    return false;
                }
                key += "_" + user.getId();
            }else{
                //do nothing
            }
            AccessKey accessKey = AccessKey.withExpire(seconds);
            Integer count = redisService.get(accessKey,key,Integer.class);
            if (count == null){
                redisService.set(accessKey,key,1);
            }else if(count < maxCount ){
                redisService.incr(accessKey,key);
            }else{
                render(response, CodeMsg.ACCESS_LIMIT_RECHED);
                return false;
            }
        }
        return true;
    }

    private void render(HttpServletResponse response, CodeMsg sessionError) throws IOException {
        response.setContentType("application/json;charset=UTF-8");//设置编码
        OutputStream out = response.getOutputStream();
        String str = JSON.toJSONString(Result.err(sessionError));
        out.write(str.getBytes("UTF-8"));
        out.flush();
        out.close();
    }

    private MiaoshaUser getUser(HttpServletRequest request, HttpServletResponse response){
        String paramToken = request.getParameter(MiaoshaUserUserServiceImp.COOKIE_NAME_TOKEN);
        String cookieToken = getCookieValue(request, MiaoshaUserUserServiceImp.COOKIE_NAME_TOKEN);
        if(StringUtils.isEmpty(cookieToken)&&StringUtils.isEmpty(paramToken)){
            return null;
        }
        String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
        return miaoshaUserService.getByToken(token,response);
    }

    private String getCookieValue(HttpServletRequest request, String cookieNameToken) {
        Cookie[] cookies = request.getCookies();
        if(cookies == null || cookies.length<= 0){
            return null;
        }
        for (Cookie cookie: cookies) {
            if(cookie.getName().equalsIgnoreCase(cookieNameToken)){
                return cookie.getValue();
            }
        }
        return null;
    }
}
